package zhoug.map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;

import org.osmdroid.api.IGeoPoint;
import org.osmdroid.api.IMapController;
import org.osmdroid.tileprovider.modules.IArchiveFile;
import org.osmdroid.tileprovider.modules.OfflineTileProvider;
import org.osmdroid.tileprovider.tilesource.FileBasedTileSource;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.CustomZoomButtonsController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;
import org.osmdroid.views.overlay.Marker;
import org.osmdroid.views.overlay.MinimapOverlay;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.OverlayManager;
import org.osmdroid.views.overlay.ScaleBarOverlay;
import org.osmdroid.views.overlay.compass.CompassOverlay;
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay;
import org.osmdroid.views.overlay.gridlines.LatLonGridlineOverlay2;
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;

import java.io.File;
import java.util.List;
import java.util.Set;

import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;

/**
 * osmdroid地图工具
 *
 * @Author: zhoug
 * @Date: 2024-12-27
 * @Description:
 */
public class MapHelper {
    private Context mContext;
    private MapView mMapView;
    /**
     * 比例尺
     */
    private ScaleBarOverlay mScaleBarOverlay;
    /**
     * 指南针
     */
    private CompassOverlay mCompassOverlay;
    /**
     * 我的位置
     */
    private MyLocationNewOverlay mMyLocationOverlay;
    private MyLocationMarker mMyLocationMarker;
    /**
     * 经纬度网格线
     */
    private LatLonGridlineOverlay2 mLatLonGridlineOverlay2;
    /**
     * 启用旋转手势
     */
    private RotationGestureOverlay mRotationGestureOverlay;
    /**
     * 内置小地图
     */
    private MinimapOverlay mMinimapOverlay;
    /**
     * 自定义事件监听层
     */
    private EventOverlay mEventOverlay;

    private final DisplayMetrics mDisplayMetrics;
    /**
     * 地图边界
     */
    private MapBound mMapBound;

    public MapHelper(@NonNull Context context, @NonNull MapView mapView) {
        mDisplayMetrics = context.getResources().getDisplayMetrics();
        this.mContext = context;
        this.mMapView = mapView;
    }

    public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
        if (lifecycleOwner != null) {
            lifecycleOwner.getLifecycle().addObserver(new DefaultLifecycleObserver() {
                @Override
                public void onResume(@NonNull LifecycleOwner owner) {
                    mMapView.onResume();
                    if (mCompassOverlay != null) {
                        mCompassOverlay.enableCompass();
                        mCompassOverlay.onResume();
                    }
                    if (mScaleBarOverlay != null) {
                        mScaleBarOverlay.onResume();
                    }
                }

                @Override
                public void onPause(@NonNull LifecycleOwner owner) {
                    mMapView.onPause();
                    if (mCompassOverlay != null) {
                        mCompassOverlay.disableCompass();
                        mCompassOverlay.onPause();
                    }
                    if (mScaleBarOverlay != null) {
                        mScaleBarOverlay.onPause();
                    }
                }

                @Override
                public void onDestroy(@NonNull LifecycleOwner owner) {
                    DefaultLifecycleObserver.super.onDestroy(owner);

                }
            });
        }
    }

    /**
     * 默认配置
     */
    public void setDefConfig() {
        mMapView.setMinZoomLevel(3.0);//最小缩放级别
        mMapView.setMaxZoomLevel(18.0);//最大缩放级别
        mMapView.setTilesScaledToDpi(true);//图块是否缩放到 DPI
        //缩放按钮配置
        CustomZoomButtonsController zoomController = mMapView.getZoomController();
        //隐藏放大缩小按钮
        zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER);
        zoomController.setZoomInEnabled(true);//放大
        zoomController.setZoomOutEnabled(true);//缩小
        mMapView.setUseDataConnection(true);
        //双指触控放大缩小
        mMapView.setMultiTouchControls(true);
        OverlayManager overlayManager = mMapView.getOverlayManager();
        //叠加层
        overlayManager.getTilesOverlay().setEnabled(true);
        // 设置地图中心点和缩放级别
        IMapController mapController = mMapView.getController();
        mapController.setZoom(3.0);
        GeoPoint point = new GeoPoint(MapConstants.BEIJING_LATITUDE, MapConstants.BEIJING_LONGITUDE); // 北京天安门的经纬度
        mapController.setCenter(point);

        if (mEventOverlay == null) {
            mEventOverlay = new EventOverlay();
            mMapView.getOverlayManager().add(mEventOverlay);
        }

        mMapView.setHasTransientState(true);
    }

    /**
     * 添加缩放比例尺
     */
    public void addScaleBarOverlay() {
        //比例尺配置
        if (mScaleBarOverlay == null) {
            mScaleBarOverlay = new ScaleBarOverlay(mMapView);
            mScaleBarOverlay.setCentred(true);
            mScaleBarOverlay.setAlignBottom(true); //底部显示
            mScaleBarOverlay.setLineWidth(2);
            mScaleBarOverlay.setMaxLength(1.5F);
            mScaleBarOverlay.setScaleBarOffset(30, 200);
            mMapView.getOverlays().add(mScaleBarOverlay);
        }

    }

    /**
     * 添加指南针
     *
     * @return
     */
    public void addCompassOverlay() {
        //指南针方向
        if (mCompassOverlay == null) {
            mCompassOverlay = new CompassOverlay(mContext, new InternalCompassOrientationProvider(mContext), mMapView);
            mCompassOverlay.enableCompass();
            mMapView.getOverlays().add(mCompassOverlay);
        }

    }

    /**
     * 添加我的位置
     * 定位图层和PolygonMask有冲突,会导致PolygonMask显示异常
     */
    @Deprecated
    public void addMyLocationOverlay() {
        if (mMyLocationOverlay == null) {
            mMyLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(mContext), mMapView);
//            mMyLocationOverlay.setDirectionIcon(null);
            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.osmap_icon_my_location);
            mMyLocationOverlay.setPersonIcon(bitmap);
            //位置周围绘制一个精度圆
            mMyLocationOverlay.setDrawAccuracyEnabled(true);
            mMapView.getOverlays().add(mMyLocationOverlay);
        }
    }

    /**
     * 设置我的位置
     * @param myLocation
     */
    public MyLocationMarker setMyLocation(GeoPoint myLocation) {
        return  setMyLocation(myLocation,false,false);

    }

    /**
     * 设置我的位置
     * @param myLocation
     * @param toCenter 移动到地图中间
     * @param anim 执行动画
     */
    public MyLocationMarker setMyLocation(GeoPoint myLocation,boolean toCenter,boolean anim) {
        if (mMyLocationMarker == null) {
            mMyLocationMarker = new MyLocationMarker(mMapView);
            List<Overlay> overlays = mMapView.getOverlays();
            overlays.add(mMyLocationMarker);
        }
        mMyLocationMarker.setPosition(myLocation);
        mMyLocationMarker.setRelatedObject(myLocation);
        if(toCenter){
            if(anim){
                mMapView.getController().animateTo(myLocation);
            }else{
                mMapView.getController().setCenter(myLocation);
                mMapView.postInvalidate();
            }
        }
        return mMyLocationMarker;
    }


    public void animateTo(IGeoPoint point) {
        IMapController controller = mMapView.getController();
        controller.animateTo(point);
    }

    /**
     * 经纬度网格线
     */
    public void addLatLonGridLineOverlay() {
        if (mLatLonGridlineOverlay2 == null) {
            mLatLonGridlineOverlay2 = new LatLonGridlineOverlay2();
            mMapView.getOverlays().add(mLatLonGridlineOverlay2);
        }

    }

    /**
     * 启用旋转手势
     */
    public void addRotationGestureOverlay() {
        if (mRotationGestureOverlay == null) {
            mRotationGestureOverlay = new RotationGestureOverlay(mMapView);
            mRotationGestureOverlay.setEnabled(true);
            mMapView.setMultiTouchControls(true);
            mMapView.getOverlays().add(mRotationGestureOverlay);
        }

    }

    /**
     * 添加内置小地图
     */
    public void addMinimapOverlay() {
        if (mMinimapOverlay == null) {

            mMinimapOverlay = new MinimapOverlay(mContext, mMapView.getTileRequestCompleteHandler());
            mMinimapOverlay.setWidth(mDisplayMetrics.widthPixels / 5);
            mMinimapOverlay.setHeight(mDisplayMetrics.heightPixels / 5);
            mMapView.getOverlays().add(mMinimapOverlay);
        }

    }

    public void addMarker(Marker marker) {
        mMapView.getOverlays().add(marker);
    }

    /**
     * 获取地图的吧边界
     *
     * @return
     */
    public MapBound getMapBound() {
        Projection projection = mMapView.getProjection();
        if (projection == null) return null;
        // 获取屏幕左上角的地理坐标
        IGeoPoint topLeft = projection.fromPixels(0, 0);
        // 获取屏幕右下角的地理坐标
        IGeoPoint bottomRight = projection.fromPixels(mMapView.getWidth(), mMapView.getHeight());
        // 通常情况下，边界框可以由左下角的点 (minLatitude, minLongitude)
        // 和右上角的点 (maxLatitude, maxLongitude) 确定
        double minLatitude = Math.min(topLeft.getLatitude(), bottomRight.getLatitude());
        double minLongitude = Math.min(topLeft.getLongitude(), bottomRight.getLongitude());
        double maxLatitude = Math.max(topLeft.getLatitude(), bottomRight.getLatitude());
        double maxLongitude = Math.max(topLeft.getLongitude(), bottomRight.getLongitude());
        if (mMapBound == null) {
            mMapBound = new MapBound();
        }
        mMapBound.setMinLatitude(minLatitude);
        mMapBound.setMinLongitude(minLongitude);
        mMapBound.setMaxLatitude(maxLatitude);
        mMapBound.setMaxLongitude(maxLongitude);
        return mMapBound;
    }

    /**
     * 判断给定的坐标是否在地图边界中
     *
     * @param mapBound
     * @param geoPoint
     * @return
     */
    public boolean isInMapBound(@NonNull MapBound mapBound, @NonNull IGeoPoint geoPoint) {
        double latitude = geoPoint.getLatitude();
        double longitude = geoPoint.getLongitude();
        return latitude >= mapBound.getMinLatitude() && latitude <= mapBound.getMaxLatitude() &&
                longitude >= mapBound.getMinLongitude() && longitude <= mapBound.getMaxLongitude();
    }


    /**
     * 限制在中国地图范围内可以滚动
     */
    public void setScrollLimitChinaBound() {
        mMapView.setScrollableAreaLimitLatitude(MapConstants.CHINA_MAX_LATITUDE, MapConstants.CHINA_MIN_LATITUDE, 0);
        mMapView.setScrollableAreaLimitLongitude(MapConstants.CHINA_MIN_LONGITUDE, MapConstants.CHINA_MAX_LONGITUDE, 0);
    }

    /**
     * 设置离线地图zip文件路径
     *
     * @param path
     * @return
     */
    public boolean setOfflineTileSourcePath(@NonNull File path) {
        SimpleRegisterReceiver simpleRegisterReceiver = new SimpleRegisterReceiver(mContext);
        OfflineTileProvider tileProvider = new OfflineTileProvider(simpleRegisterReceiver, new File[]{path});
        mMapView.setTileProvider(tileProvider);
        IArchiveFile[] archives = tileProvider.getArchives();
        if (archives != null && archives.length > 0) {
            Set<String> tileSources = archives[0].getTileSources();
            if (tileSources != null && !tileSources.isEmpty()) {
                String source = tileSources.iterator().next();
                mMapView.setTileSource(FileBasedTileSource.getSource(source));
                return true;
            }
        }
        return false;
    }

    public void setOnClickMapListener(OnClickMapListener onClickMapListener) {
        if (mEventOverlay != null) {
            mEventOverlay.setOnClickMapListener(onClickMapListener);
        }
    }

    /**
     * 是否触摸在地图上
     *
     * @return
     */
    public boolean isTouchMap() {
        if (mEventOverlay != null) {
            return mEventOverlay.isTouched();
        }
        return false;
    }

    /**
     * 移除所有marker
     *
     * @param invalidate 是否刷新地图
     */
    public void removeAllMarkers(boolean invalidate) {
        if (mMapView != null) {
            List<Overlay> overlays = mMapView.getOverlays();
            if (overlays != null && !overlays.isEmpty()) {
                for (int i = overlays.size() - 1; i >= 0; i--) {
                    Overlay overlay = overlays.get(i);
                    if (overlay instanceof Marker) {
                        overlays.remove(overlay);
                    }
                }
            }
            if (invalidate) {
                mMapView.postInvalidate();
            }
        }
    }

    /**
     * 指南针
     *
     * @return
     */
    public CompassOverlay getCompassOverlay() {
        return mCompassOverlay;
    }

    /**
     * 比例尺
     *
     * @return
     */
    public ScaleBarOverlay getScaleBarOverlay() {
        return mScaleBarOverlay;
    }

    /**
     * 我的位置
     *
     * @return
     */
    public MyLocationNewOverlay getMyLocationOverlay() {
        return mMyLocationOverlay;
    }

    /**
     * 经纬度网格线
     *
     * @return
     */
    public LatLonGridlineOverlay2 getLatLonGridlineOverlay2() {
        return mLatLonGridlineOverlay2;
    }
}
